﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Brainee.Search
{
  /// <summary>
  /// AIMA formal definition of a problem (see AIMA, 2nd ed., p 62)
  /// </summary>
  /// <remarks>
  /// A problem consists of four parts: the initial state, a set of actions, a goal test function,
  /// and a path cost function. The environment of the problem is represented by a state space.
  /// A path through the state space from the initial state to a goal state is a solution.
  /// </remarks>
  public interface IProblem
  {
    /// <summary>
    /// Get or set the initial state that the agent starts in.
    /// </summary>
    IState InitialState { get; set; }

    /// <summary>
    /// Gets the IEqualityComparer<IState> object that is used
    /// to determine equality of two IState instances.
    /// </summary>
    IEqualityComparer<IState> StateComparer { get; }

    /// <summary>
    /// A description of the possible actions available to the agent for a given state. 
    /// </summary>
    /// <param name="state"></param>
    /// <returns>
    /// Given a particular state, Successor returns a set of (action, successor) ordered pairs,
    /// where each action is one of the legal actions in current state and each successor is a 
    /// state that can be reached from the current one by applying the action.
    /// </returns>
    IEnumerable<ActionState> Successors (IState state);

    /// <summary>
    /// Determines whether a given state is a goal state.
    /// </summary>
    /// <param name="state"></param>
    /// <returns></returns>
    bool GoalTest (IState state);

    /// <summary>
    /// Returns an estimation of the cost from <paramref name="state"/> to goal state.
    /// </summary>
    /// <param name="state"></param>
    /// <returns>
    /// This method is optional, but must be implemented in order to use informed
    /// strategies to solve this problem.
    /// </returns>
    double EstimatedCostToGoal (IState state);

    /// <summary>
    /// The step cost of taking action <paramref name="action"/> to go from state 
    /// <paramref name="from"/> to state <paramref name="to"/>
    /// </summary>
    /// <param name="from">Initial state</param>
    /// <param name="action">Taken action</param>
    /// <param name="to">Targeted state</param>
    /// <returns></returns>
    double StepCost (IState from, IAction action, IState to);
  }
}
